package com.xm.web.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.pagehelper.PageInfo;
import com.github.pagehelper.page.PageMethod;
import com.xm.common.utils.StrPool;
import com.xm.web.consts.MagicNumEnum;
import com.xm.web.entity.PageResult;
import com.xm.web.entity.po.TbPermission;
import com.xm.web.entity.po.TbUser;
import com.xm.web.entity.request.UserRequest;
import com.xm.web.entity.response.UserResponse;
import com.xm.web.mapper.TbUserMapper;
import com.xm.web.service.ITbPermissionService;
import com.xm.web.service.ITbRoleService;
import com.xm.web.service.ITbUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xm.web.utils.PermissionTreeUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @author yousj
 * @since 2021-08-18
 */
@Service
@RequiredArgsConstructor
public class TbUserServiceImpl extends ServiceImpl<TbUserMapper, TbUser> implements ITbUserService, UserDetailsService {

    private final PasswordEncoder passwordEncoder;
    private final ITbRoleService roleService;
    private final ITbPermissionService permissionService;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        TbUser user = getOne(Wrappers.<TbUser>lambdaQuery().eq(TbUser::getUsername, username));
        if (Objects.isNull(user)) throw new UsernameNotFoundException(StrPool.EMPTY);
        List<Integer> rules = roleService.selectRulesByUser(username).stream().map(r -> r.split(StrPool.COMMA))
                .flatMap(Arrays::stream).map(Integer::valueOf).collect(Collectors.toList());
        List<TbPermission> permissions = permissionService.list(Wrappers.<TbPermission>lambdaQuery()
                .eq(TbPermission::getStatus, MagicNumEnum.ON.getCode())
                .in(!rules.contains(MagicNumEnum.ROOT.getCode()), TbPermission::getId, rules));
        List<GrantedAuthority> authorities = AuthorityUtils.commaSeparatedStringToAuthorityList(permissions.stream().map(TbPermission::getPermissionRule).collect(Collectors.joining(StrPool.COMMA)));
        // 用户拥有的权限列表
        user.setAuthorities(authorities);
        // 用户拥有的菜单列表
        user.setMenus(PermissionTreeUtil.permissions2tree(permissions.stream().filter(p -> Objects.equals(p.getPermissionType(), MagicNumEnum.PERMISSION_MENU.getCode())).collect(Collectors.toList())));
        return user;
    }

    @Override
    public PageResult<UserResponse> pageList(UserRequest request) {
        PageInfo<UserResponse> pageInfo = PageMethod.startPage(request.getPageNum(), request.getPageSize()).doSelectPageInfo(
                () -> list(Wrappers.lambdaQuery(BeanUtil.copyProperties(request, TbUser.class))));
        pageInfo.setList(BeanUtil.copyToList(pageInfo.getList(), UserResponse.class));
        return PageResult.of(pageInfo);
    }

    @Override
    public UserResponse selectById(Integer id) {
        return BeanUtil.copyProperties(getById(id), UserResponse.class);
    }

    @Override
    public boolean save(UserRequest request) {
        TbUser user = BeanUtil.copyProperties(request, TbUser.class);
        user.setPassword(passwordEncoder.encode(user.getPassword()));
        return save(user);
    }

    @Override
    public boolean update(UserRequest request) {
        TbUser user = BeanUtil.copyProperties(request, TbUser.class);
        user.setPassword(null);
        return updateById(user);
    }
}
